/*
 * uart.c
 *
 *  Created on: Jun 10, 2024
 *      Author: PIANO
 */
#include "uart.h"
#include "modbus.h"

/**
 * externs
 *
 */
extern UART_HandleTypeDef huart1;
extern UART_HandleTypeDef huart2;
extern UART_HandleTypeDef huart3;

/**
 * globals
 *
 */
UART_DataTypeDef duart1;
UART_DataTypeDef duart2;
UART_DataTypeDef duart3;

/**
 * UART初始化
 *
 * @param
 * @return
 */
void uartSetup(void) {

}

/**
 * UART循环
 *
 * @param
 * @return
 */
void uartLoop(void) {
	// uart1 modbus主机
	static uint16_t index = 0;
	uint16_t data[4];

	duart1.intervalSet = 300;
	duart1.timeOutSet = 1000;
	duart1.retryTimesSet = 2;

	// 从机1
	if (index == 0) {
		duart1.status = UART_IDLE;
		index++;
	} else if (index == 1) {
		// 04读取
		modbusMaster(&huart1, &duart1, 1, 4, 2, 4, data);
		// 完成
		if (duart1.status >= UART_OK) {
			// 成功
			if (duart1.status == UART_OK) {

				float t = u16ToFloat(data);
				holdingRegister[0] = (int16_t) (t * 10.0);
				float h = u16ToFloat(&data[2]);
				holdingRegister[1] = (int16_t) (h * 10.0);
			}
			// 失败
			else {

			}
			// 索引增加
			index++;
		}
	}
	// 其他
	else {
		index = 0;
	}
	// uart2 modbus从机
	MODBUS_SlaveDataTypeDef slaveData;
	slaveData.address = 1;
	slaveData.pCoilStatus = coil;
	slaveData.coilCount = 32;
	slaveData.pDiscreteInput = discreteInput;
	slaveData.discreteInputCount = 32;
	slaveData.pInputRegister = inputRegister;
	slaveData.inputRegisterCount = 32;
	slaveData.pHoldingRegister = holdingRegister;
	slaveData.holdingRegisterCount = 32;

	modbusSlave(&huart2, &duart2, &slaveData);
	// 通讯灯
	GPIO_PinState ledState =
			duart2.timeOut < 100 ? GPIO_PIN_SET : GPIO_PIN_RESET;
	LED_COM(ledState);
	// 如果长时间接受不到数据，关闭IOT模块电源5S后重新上电
	int _resetTime = 60;
	IOT_PWR(duart2.timeOut <= (_resetTime * 1000));
	// 关闭5S后重新计时
	if (duart2.timeOut > (_resetTime + 5) * 1000) {
		duart2.timeOut = 0;
	}
	// 串口空闲时间
	inputRegister[5] = duart1.timeOut / 1000;
	inputRegister[6] = duart2.timeOut / 1000;
	inputRegister[7] = duart3.timeOut / 1000;
}

/**
 * 根据huart获取duart
 *
 * @param
 * @return
 */
UART_DataTypeDef* getDuart(UART_HandleTypeDef *huart) {

	if (huart == &huart1)
		return &duart1;
	else if (huart == &huart2)
		return &duart2;
	else if (huart == &huart3)
		return &duart3;
	else
		return 0;
}

/**
 * uart任务
 *
 * @param
 * @return
 */
void uartTask1ms(void) {
	// duart1
	if (duart1.timeOut < MAX_TIME_OUT)
		duart1.timeOut++;
	if (duart1.interval < MAX_INTERVAL)
		duart1.interval++;
	// duart2
	if (duart2.timeOut < MAX_TIME_OUT)
		duart2.timeOut++;
	if (duart2.interval < MAX_INTERVAL)
		duart2.interval++;
	// duart3
	if (duart3.timeOut < MAX_TIME_OUT)
		duart3.timeOut++;
	if (duart3.interval < MAX_INTERVAL)
		duart3.interval++;
}

/**
 * UART 发送
 *
 * @param
 * @return
 */
void uartSend(UART_HandleTypeDef *huart, UART_DataTypeDef *duart) {

	//判断发送字节数
	if (duart->txCount < 1)
		return;
	//设置发送总量及索引
	huart->TxXferSize = duart->txCount;
	huart->TxXferCount = 0;
	//使能TXE中断
	__HAL_UART_ENABLE_IT(huart, UART_IT_TXE);
	//清除发送计数
	duart->txCount = 0;
}

/**
 * UART 接收字节
 *
 * @param
 * @return
 */
static void receiveByte(UART_HandleTypeDef *huart) {
	// 读取数据会自动清除RXNE标志，在此先将数据读出，防止溢出错误
	uint8_t data = (uint8_t) (huart->Instance->DR & 0xFF);
	// 获取 duart
	UART_DataTypeDef *duart = getDuart(huart);
	//判断与上次接收的间隔
	if (duart->timeOut > 100)
		duart->rxCount = 0;
	//判断数据接收到的数据长度
	if (duart->rxCount < BUFFER_SIZE) {
		duart->rxBuffer[duart->rxCount] = data;
		duart->rxCount++;
	}
	//接收数据计时器清零
	duart->timeOut = 0;
}

/**
 * UART 发送字节
 *
 * @param
 * @return
 */
static void sendByte(UART_HandleTypeDef *huart) {
	// 获取 duart
	UART_DataTypeDef *duart = getDuart(huart);
	// 判断是否有数据需要发送
	if (huart->TxXferCount < huart->TxXferSize) {
		// 有数据要发送
		huart->Instance->DR = (uint8_t) duart->txBuffer[huart->TxXferCount];
		huart->TxXferCount++;
	} else {
		// 没有更多数据要发送时，清零数据指针，禁用TXE中断
		huart->TxXferSize = 0;
		huart->TxXferCount = 0;
		__HAL_UART_DISABLE_IT(huart, UART_IT_TXE);
	}
}

/**
 * UART 中断处理
 *
 * @param
 * @return
 */
void uartIsr(UART_HandleTypeDef *huart) {

	uint32_t _flag = 0, _it_source = 0;
	// receive
	_flag = __HAL_UART_GET_FLAG(huart, UART_FLAG_RXNE);
	_it_source = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_RXNE);
	if ((_flag != RESET) && (_it_source != RESET)) {
		receiveByte(huart);
	}
	// send
	_flag = __HAL_UART_GET_FLAG(huart, UART_FLAG_TXE);
	_it_source = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_TXE);
	if ((_flag != RESET) && (_it_source != RESET)) {
		__HAL_UART_CLEAR_FLAG(huart, UART_FLAG_TXE);
		sendByte(huart);
	}
	//发送完成
	_flag = __HAL_UART_GET_FLAG(huart, UART_FLAG_TC);
	_it_source = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_TC);
	if ((_flag != RESET) && (_it_source != RESET)) {
		__HAL_UART_CLEAR_FLAG(huart, UART_FLAG_TC);
		//可控制收发引脚转换
		__HAL_UART_DISABLE_IT(huart, UART_IT_TC);
	}
	// 溢出错误
	_flag = __HAL_UART_GET_FLAG(huart, UART_FLAG_ORE);
	if (_flag != RESET) {
		__HAL_UART_CLEAR_FLAG(huart, UART_FLAG_ORE);
		// 溢出的数据丢弃
		// receiveByte(huart);
	}
	// 其他错误
	_flag =
			__HAL_UART_GET_FLAG(huart,
					UART_FLAG_CTS | UART_FLAG_LBD | UART_FLAG_NE | UART_FLAG_FE | UART_FLAG_PE);
	if (_flag != RESET) {
		__HAL_UART_CLEAR_FLAG(huart,
				UART_FLAG_CTS | UART_FLAG_LBD | UART_FLAG_NE | UART_FLAG_FE | UART_FLAG_PE);
	}
}
